//----------------------------------------------------------------------------
// M A R I T I M E  R E S E A R C H  I N S T I T U T E  N E T H E R L A N D S
//----------------------------------------------------------------------------
// Copyright (C) 2008 - MARIN - All rights reserved - http://www.marin.nl
//----------------------------------------------------------------------------
// Program    : mermaid
// Module     : vbm
// File       : FileReader.cpp
//----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "StringUtils.h"
#include "FileReader.h"
#include "assertplus.h"

#ifdef _WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data
#pragma warning(disable: 4996) // This function or variable may be unsafe
#endif

#define BUFLEN 200

/// constructor
FileReader::FileReader(const char *name /** file name */)
: m_fp(0)
, m_filename(name)
{
    m_fp = fopen(name, "r");
}

/// destructor
FileReader::~FileReader()
{
    fclose(m_fp);
}

/// returns name of open file
std::string FileReader::getFileName() const
{
    return m_filename;
}

/// checks if end-of-file was reached
bool FileReader::Eof()
{
    return feof(m_fp) != 0;
}

/// reads first integer from line in file fp
int FileReader::ReadInt()
{
    char buffer[BUFLEN];
    char *words[2];
    ReadCompleteLine(buffer);
    StringUtils::split(buffer, words, 2, ' ');
    return atoi(StringUtils::trim(words[0]));
}

/// reads first float from line in file fp
REAL FileReader::ReadFloat()
{
    char buffer[BUFLEN];
    char *words[2];
    ReadCompleteLine(buffer);
    StringUtils::split(buffer, words, 2, ' ');
    return atof(StringUtils::trim(words[0]));
}

/// reads first boolean from line in file fp
bool FileReader::ReadBoolean()
{
    char buffer[BUFLEN];
    char *words[2];
    ReadCompleteLine(buffer);
    StringUtils::split(buffer, words, 2, ' ');
    char *value = StringUtils::trim(words[0]);
    if (!(!strcmp(value, "true") || !strcmp(value, "false")))
    {
        fprintf(stderr, "boolean expected, got: %s\n", value);
        exit(-1);
    }
    return strcmp(value, "true") == 0;
}

/// reads first string from line in file fp
std::string FileReader::ReadString()
{
    char buffer[BUFLEN];
    char *words[2];
    ReadCompleteLine(buffer);
    if (strlen(buffer) == 0)
    {
        return std::string("");
    }
    StringUtils::split(buffer, words, 2, ' ');
    return StringUtils::trim(words[0]);
}

/// reads four values from line in file fp
void FileReader::ReadLine(REAL *a, REAL *b, REAL *c, bool *d)
{
    char buffer[BUFLEN];
    char *words[4];
    char *ptr;
    ReadCompleteLine(buffer);
    ptr = StringUtils::trim(buffer);
    StringUtils::split(ptr, words, 2, '%');
    StringUtils::split(words[0], words, 4, ' ');
    *a = atof(StringUtils::trim(words[0]));
    *b = atof(StringUtils::trim(words[1]));
    *c = atof(StringUtils::trim(words[2]));
    *d = strcmp(StringUtils::trim(words[3]), "T") == 0;
}

/// reads two float values from line in file fp
void FileReader::ReadFloats(REAL *a, REAL *b)
{
    char buffer[BUFLEN];
    char *words[2];
    char *ptr;
    ReadCompleteLine(buffer);
    ptr = StringUtils::trim(buffer);
    StringUtils::split(ptr, words, 2, '%');
#ifdef DEBUG
    int n =
#endif
    StringUtils::split(words[0], words, 2, ' ');
    ASSERT(n == 2, "line should contain 2 values"); // TODO should be real runtime error
    *a = atof(StringUtils::trim(words[0]));
    *b = atof(StringUtils::trim(words[1]));
}

/// reads four float values from line in file fp
void FileReader::ReadFloats(REAL *a, REAL *b, REAL *c, REAL *d)
{
    char buffer[BUFLEN];
    char *words[4];
    char *ptr;
    ReadCompleteLine(buffer);
    ptr = StringUtils::trim(buffer);
    StringUtils::split(ptr, words, 2, '%');
#ifdef DEBUG
    int n =
#endif
    StringUtils::split(words[0], words, 4, ' ');
    ASSERT(n == 4, "line should contain 4 values"); // TODO should be real runtime error
    *a = atof(StringUtils::trim(words[0]));
    *b = atof(StringUtils::trim(words[1]));
    *c = atof(StringUtils::trim(words[2]));
    *d = atof(StringUtils::trim(words[3]));
}

/// reads section string [xxxxx]
std::string FileReader::ReadSection()
{
    char buffer[BUFLEN];
    ReadCompleteLine(buffer);
    return buffer;
}

/// reads one line from file
void FileReader::ReadCompleteLine(char *line)
{
    line[0] = '\0';
    char buffer[BUFLEN + 1];
    char *ptr;
    char* ignore;
    do
    {
        ignore = fgets(buffer, BUFLEN, m_fp);
        buffer[BUFLEN] = '\0';
        ptr = StringUtils::trim(buffer);
        char *p = strchr(ptr, '#');
        if (p)
        {
            *p = '\0';
        }
        ptr = StringUtils::trim(ptr);
    }
    while (!feof(m_fp) && !ptr[0]);
    strcpy(line, buffer);
}

